package com.qiangesoft.blog.system.authentication;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import com.google.code.kaptcha.Producer;
import com.qiangesoft.blog.common.constants.Constants;
import com.qiangesoft.blog.common.constants.RedisConstants;
import com.qiangesoft.blog.common.utils.UUIDUtils;
import com.qiangesoft.blog.system.entity.SysUser;
import com.qiangesoft.blog.system.exception.BusinessException;
import com.qiangesoft.blog.system.pojo.dto.LoginDTO;
import com.qiangesoft.blog.system.redis.RedisService;
import com.qiangesoft.blog.system.service.ISysUserService;
import com.qiangesoft.blog.system.utils.AesEncryptUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.FastByteArrayOutputStream;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.qiangesoft.blog.common.result.ResultCode.ERROR_PASSWORD;

/**
 * 登录服务
 *
 * @author qiange
 * @date 2023-06-01
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LoginServiceImpl implements LoginService {

    private final ISysUserService userService;

    private final RedisService redisService;

    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;

    @Override
    public Map<String, String> getCode() throws IOException {
        Map<String, String> result = new HashMap<>();
        // 生成验证码的UUID
        String uuid = UUIDUtils.getUuid();
        String capStr = null;
        String code = null;
        BufferedImage image = null;
        // 生成验证码
        String capText = captchaProducerMath.createText();
        capStr = capText.substring(0, capText.lastIndexOf("@"));
        code = capText.substring(capText.lastIndexOf("@") + 1);
        image = captchaProducerMath.createImage(capStr);
        redisService.setCacheObject(RedisConstants.CAPTCHA_CODE + uuid, code, RedisConstants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // 转换流信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        ImageIO.write(image, "jpg", os);
        result.put("uuid", uuid);
        result.put("img", Base64.encode(os.toByteArray()));
        return result;
    }

    @Override
    public String login(LoginDTO dto) {
        // 校验验证码
        Object cacheObject = redisService.getCacheObject(RedisConstants.CAPTCHA_CODE + dto.getUuid());
        if (cacheObject == null) {
            throw new BusinessException("验证码已失效!");
        }
        if (!cacheObject.equals(dto.getCode())) {
            throw new BusinessException("验证码错误!");
        }
        // 校验用户名和密码
        SysUser user = userService.getByUsername(dto.getUsername());
        Assert.isTrue(user == null || !AesEncryptUtils.aesEncrypt(dto.getPassword()).equals(user.getPassword()), ERROR_PASSWORD.getDesc());

        // 记住我7天免登录
        if (dto.getRememberMe()) {
            StpUtil.login(user.getId(), new SaLoginModel().setTimeout(60 * 60 * 24 * 7));
        } else {
            StpUtil.login(user.getId());
        }
        StpUtil.getSession().set(Constants.CURRENT_USER, userService.getUserById(user.getId()));
        return StpUtil.getTokenValue();
    }
}
